package com.htfyun.factorytest;

import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.htfyun.factorytest.agingtest.TestEmmcController;
import com.htfyun.factorytest.common.FTUtils;
import com.htfyun.factorytest.common.PermissionManager;
import com.htfyun.factorytest.utils.DebugLog;
import com.htfyun.factorytest.utils.FileReadWrite;
import com.htfyun.factorytest.utils.TimeStringUtils;
import com.htfyun.eink.EinkUtils;

import java.io.File;
import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class EmmcTestActivity extends SingleTestBaseActivity implements View.OnClickListener, TestEmmcController.OnWROverListener {


    private EditText editCount;

    private TextView txtLog;

    private Context mContext;

    private int needTestCount = 3;
    private int testCount = 0;

    private MyHandler handler;

    private final static String PATH_TEST_EMMC_FAIL = FTUtils.getFTStorageDirectory() + File.separator + "emmcTestFail.log";

    private List<TestEmmcController.EmmcInfo> emmcTestWriteList = new ArrayList<>();
    private List<TestEmmcController.EmmcInfo> emmcTestReadList = new ArrayList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //设置窗体始终点亮
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.activity_emmc);

        mContext = this;

        editCount = findViewById(R.id.editCount);
        txtLog = findViewById(R.id.txtLog);

        findViewById(R.id.btnStart).setOnClickListener(this);
        findViewById(R.id.btnStop).setOnClickListener(this);
        findViewById(R.id.btnExit).setOnClickListener(this);

        handler = new MyHandler(this);

        editCount.setSelection(editCount.getText().length());

        initPermission();
    }

    @Override
    protected void onResume() {
        super.onResume();
        EinkUtils.setCpuFreq(mContext, EinkUtils.CPU_FREQ_LEVEL_MAX, true);
    }

    @Override
    protected void onPause() {
        super.onPause();
        EinkUtils.resetCpuFreqParam(mContext);
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopTestEmmc();
    }

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.btnStart:
                txtLog.setText("");
                startTestEmmc();
                break;
            case R.id.btnStop:
                stopTestEmmc();
                break;
            case R.id.btnExit:
                stopTestEmmc();
                setResult(RESULT_OK);
                ActivityCompat.finishAfterTransition(this);
                break;
        }

    }

    private void initPermission() {
        //如果无权限就申请然后回调，如果有权限就执行录音监听
        if (!isGotPermission()) {
            //同时申请多个权限
            PermissionManager.getInstance(getApplicationContext()).execute(this,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE);

        }

    }

    private boolean isGotPermission() {

        return ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;

    }

    //如果有权限的话返回
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        PermissionManager.getInstance(getApplicationContext()).
                onRequestPermissionsResult(requestCode, permissions, grantResults);

        DebugLog.w(" ~~~~~~~~~~~~~~onRequestPermissionsResult");

    }


    @Override
    public void onWriteOverListener(TestEmmcController.EmmcInfo info, long time_ms) {
        updateLog("write over: emmcInfo = " + info + ", used time: " + TimeStringUtils.makeTimeString(time_ms));

        emmcTestWriteList.remove(info);
        checkTestEmmcAndTryStartAgain();
    }

    @Override
    public void onReadOverListener(TestEmmcController.EmmcInfo info, long time_ms) {

        updateLog("read over: emmcInfo = " + info + ", used time: " + TimeStringUtils.makeTimeString(time_ms));

        emmcTestReadList.remove(info);
        checkTestEmmcAndTryStartAgain();
    }

    @Override
    public void onTestFailed(TestEmmcController.EmmcInfo info, String filePath, long offset, byte shouldValue, byte realValue) {

        String log = now2String() + "-> onTestFailed : info = " + info + ", filePath " + filePath
                + ", offset = " + offset
                + ", shouldValue =  0x" + Integer.toHexString((0xff & shouldValue))
                + ", realValue = 0x" + Integer.toHexString((0xff & realValue))
                + "\n";


        FileReadWrite.writeAppendFile(PATH_TEST_EMMC_FAIL, log);

        updateLog("EMMC error occurred, log path = " + PATH_TEST_EMMC_FAIL);

    }

    private final ThreadLocal<SimpleDateFormat> SDF_THREAD_LOCAL = new ThreadLocal<>();

    @NonNull
    private SimpleDateFormat getDefaultFormat() {
        SimpleDateFormat simpleDateFormat = SDF_THREAD_LOCAL.get();
        if (simpleDateFormat == null) {
            simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.getDefault());
            SDF_THREAD_LOCAL.set(simpleDateFormat);
        }
        return simpleDateFormat;
    }

    private String now2String() {
        return getDefaultFormat().format(new Date());
    }

    /////////////////////
    // cank TestItemHardware.java 里的 test emmc
    private void startTestEmmc() {

        updateLog("Start Test Emmc");
        testCount = 0;
        CharSequence defaultCount = editCount.getText();
        if (!TextUtils.isEmpty(defaultCount) && TextUtils.isDigitsOnly(defaultCount)) {
            needTestCount = Integer.parseInt(defaultCount.toString());
        }
        doStartTestEmmc();
    }

    private void doStartTestEmmc() {

        if (testCount > needTestCount) {
            updateLog("Test emmc count is " + testCount + ", No more emmc test");
            return;
        }


        for (TestEmmcController.EmmcInfo info : TestEmmcController.EmmcInfo.values()) {
            if (!emmcTestWriteList.contains(info)) {
                emmcTestWriteList.add(info);
            }
            if (!emmcTestReadList.contains(info)) {
                emmcTestReadList.add(info);
            }
        }

        updateLog("Test emmc count is " + testCount + ", keep emmc test");


        TestEmmcController.getInstance().addOnWROverListener(this);
        TestEmmcController.getInstance().setMarginSpace((testCount) * TestEmmcController._128_M);
        TestEmmcController.getInstance().setContext(mContext);
        TestEmmcController.getInstance().startTest();

    }

    private void stopTestEmmc() {

        updateLog("Stop Test Emmc");

        TestEmmcController.getInstance().removeOnWROverListener(this);
        TestEmmcController.getInstance().stopTest();

    }


    private void checkTestEmmcAndTryStartAgain() {

        if (!(emmcTestReadList.isEmpty() && emmcTestWriteList.isEmpty())) {
            return;
        }

        testCount++;

        stopTestEmmc();
        TestEmmcController.getInstance().deleteTestFiles();

        doStartTestEmmc();

    }


    private void updateLog(String log) {
        handler.obtainMessage(MyHandler.MSG_UPDATE_LOG, log).sendToTarget();
    }
    private void doUpdateLog(String log) {
        String txt = txtLog.getText().toString();
        if (txt.length() > 1024 * 6) {
            txtLog.setText(log);
        } else {
            txtLog.setText(txt + "\n" + log);
        }
    }

    private static class MyHandler extends Handler {


        public static final int MSG_UPDATE_LOG = 100;
        private final WeakReference<EmmcTestActivity> activityWeakReference;

        private MyHandler(EmmcTestActivity activity) {
            super(Looper.getMainLooper());

            activityWeakReference = new WeakReference<EmmcTestActivity>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            //弱引用会在下一次gc时回收
            EmmcTestActivity activity = activityWeakReference.get();
            if (activity == null) {
                return;
            }

            switch (msg.what) {
                case MSG_UPDATE_LOG:
                    activity.doUpdateLog((String) msg.obj);
                    break;
                default:
                    break;
            }

        }
    }


}
